package gov.pbc.nn.kjgl.joinjrfwygl.view;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.bstek.bdf2.core.business.IUser;
import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.orm.ParseResult;
import com.bstek.bdf2.core.orm.hibernate.ISessionCallback;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.core.Configure;
import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;
import com.bstek.dorado.data.variant.Record;
import com.bstek.dorado.uploader.DownloadFile;
import com.bstek.dorado.uploader.UploadFile;
import com.bstek.dorado.uploader.annotation.FileProvider;
import com.bstek.dorado.uploader.annotation.FileResolver;
import com.bstek.uflo.client.service.ProcessClient;
import com.bstek.uflo.client.service.TaskClient;
import com.bstek.uflo.designer.utils.EscapeUtils;
import com.bstek.uflo.model.ProcessInstance;
import com.bstek.uflo.model.task.Task;
import com.bstek.uflo.query.ProcessInstanceQuery;
import com.bstek.uflo.service.ProcessService;
import com.bstek.uflo.service.StartProcessInfo;
import com.bstek.uflo.service.TaskService;

import gov.pbc.nn.core.bdf.entity.Dept;
import gov.pbc.nn.core.bdf.service.UserService.DefaultUserRowMapper;
import gov.pbc.nn.core.dao.CommonJdbcDao;
import gov.pbc.nn.core.dao.PbcnnCoreHibernateDao;
import gov.pbc.nn.core.dao.PbcnnCoreJdbcDao;
import gov.pbc.nn.core.entity.BaseEntity;
import gov.pbc.nn.core.utils.EntityRowMapperUtils;
import gov.pbc.nn.core.utils.GetTableUtils;
import gov.pbc.nn.core.utils.SecurityUtils;
import gov.pbc.nn.kjgl.Constants;
import gov.pbc.nn.kjgl.joinjrfwygl.dao.JoinJrfwyglDao;
import gov.pbc.nn.kjgl.joinjrfwygl.entity.HandleDept;
import gov.pbc.nn.kjgl.joinjrfwygl.entity.HandleInfo;
import gov.pbc.nn.kjgl.joinjrfwygl.entity.JoinJrfwygl;
import gov.pbc.nn.kjgl.xkyyh.entity.NewBank;
import gov.pbc.nn.kjgl.xkyyh.entity.TrainDept;
import gov.pbc.nn.kjgl.xkyyh.view.NewBankPR.TrainDeptMapper;
import gov.pbc.nn.uflo.UfloUtils;
import gov.pbc.nn.uflo.entity.Opinion;

@Component("joinPR")
public class JoinPR {

	@Autowired
	private JoinJrfwyglDao joinDao;
	

	@Resource(name = PbcnnCoreHibernateDao.BEAN_ID)
	private PbcnnCoreHibernateDao coreHibernateDao;
	

	@Resource(name = CommonJdbcDao.BEAN_ID)
	private CommonJdbcDao commonJdbcDao;

	@Autowired
	@Qualifier(ProcessClient.BEAN_ID)
	private ProcessClient processClient;
	
	@Autowired
	@Qualifier(TaskClient.BEAN_ID)
	private TaskClient tc;

	@Autowired
	@Qualifier(TaskService.BEAN_ID)
	private TaskService taskService;

	@Autowired
	@Qualifier(ProcessService.BEAN_ID)
	private ProcessService processService;
	
	@Resource(name = ProcessClient.BEAN_ID)
	private ProcessClient pc;
	
	public class JoinMapper implements RowMapper<JoinJrfwygl>{
		@Override
		public JoinJrfwygl mapRow(ResultSet rs, int rowNum) throws SQLException {
			return EntityRowMapperUtils.get(JoinJrfwygl.class, rs, rowNum);
		}		
	}
	
	public class HandleDeptMapper implements RowMapper<HandleDept>{
		@Override
		public HandleDept mapRow(ResultSet rs, int rowNum) throws SQLException {
			return EntityRowMapperUtils.get(HandleDept.class, rs, rowNum);
		}		
	}
	
	public class HandleInfoMapper implements RowMapper<HandleInfo>{
		@Override
		public HandleInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
			return EntityRowMapperUtils.get(HandleInfo.class, rs, rowNum);
		}		
	}

	@DataProvider
	public JoinJrfwygl loadJoinJrfwygl(String id) throws Exception {
		if (StringUtils.isEmpty(id)) {
			return null;
		}
		JoinJrfwygl joinJrfwygl = (JoinJrfwygl) this.joinDao.get(
				 id,JoinJrfwygl.class);	
		return joinJrfwygl;
	}
	
	@DataProvider
	public List<HandleDept> loadHandleDepts(String id) {
		String sql = "SELECT\n"
				+ "			D.* \n"
				+ "		FROM\n"
				+ "			t_handle_dept D\n"
				+"WHERE\n" 
				+"	D.INVALID_=0 and D.JOIN_ID_=?";
		return this.commonJdbcDao.getJdbcTemplate().query(sql, new Object[] { id },new HandleDeptMapper());	
	}
	
	@DataProvider
	public HandleInfo loadHandleInfo(String id) {
		
		String sql = "SELECT\n"
				+ "			H.* \n"
				+ "		FROM\n"
				+ "			t_handle_info H\n"
				+"WHERE\n" 
				+"	H.INVALID_=0 and H.HandleDept_ID_=?";
		List<HandleInfo> handleInfos=	this.commonJdbcDao.getJdbcTemplate().query(sql, new Object[] { id },new HandleInfoMapper());		
		if(handleInfos!=null&&handleInfos.size()>0)
			return handleInfos.get(0);
		else return new HandleInfo();
	}
	
	@DataProvider
	public HandleDept loadHandleDeptByLoginUser(String joinId) throws Exception {
		String deptId=((Dept)ContextHolder.getLoginUser().getDepts().get(0)).getCDept().getId();
		String sql = "SELECT\n"
				+ "			D.* \n"
				+ "		FROM\n"
				+ "			t_handle_dept D\n"
				+"WHERE\n" 
				+"	D.INVALID_=0 and D.DEPT_ID_ = ? and D.JOIN_ID_=?";
		List<HandleDept> handleDepts=	this.commonJdbcDao.getJdbcTemplate().query(sql, new Object[] { deptId, joinId },new HandleDeptMapper());		
		if(handleDepts!=null&&handleDepts.size()>0)
			return handleDepts.get(0);
		else return null;
	}
	
	@DataProvider
	public  List<IUser> getdeptUsers()
	{
		 try {
			 String sql="select u.* from T_USER u,bdf2_user_dept ud where u.USERNAME_=ud.USERNAME_ and ud.DEPT_ID_ like ?";
			 PbcnnCoreJdbcDao jdbc = ContextHolder.getBean(PbcnnCoreJdbcDao.BEAN_ID);
			 List<IUser> users = jdbc.getJdbcTemplate().query(sql,
						new Object[] { ContextHolder.getLoginUser().getDepts().get(0).getId()+"%" }, new DefaultUserRowMapper());
			 return users;
		} catch (Exception e) {
			e.printStackTrace();
			return new ArrayList<IUser>();
			// TODO: handle exception
		}
	}
	
	@DataProvider
	public void getJoinJrfwyglPage(Page<JoinJrfwygl> page, Criteria criteria) throws Exception{
		String sql = "SELECT\n"
				+ "			J.* \n"
				+ "		FROM\n"
				+ "			t_join_jrfwygl J\n"
				+"WHERE\n" 
				+"	J.INVALID_=0 ";
//		if(!this.commonJdbcDao.containsProperty("state", criteria)){
//			sql += "  and j.state_ in (0,10) ";
//		}
		ParseResult result = this.commonJdbcDao.parseCriteria(criteria, true, "J");
		if (result != null) {
			StringBuffer sb = result.getAssemblySql();
			Map<String, Object> valueMap = result.getValueMap();
			sql += " and "+sb.toString() +" order by J.CREATE_DATE_,J.UPDATE_DATE_ ";
			this.commonJdbcDao.pagingQuery(page, sql,new JoinMapper(),valueMap);
		} else {
			sql +=" order by J.CREATE_DATE_,J.UPDATE_DATE_ ";
			this.commonJdbcDao.pagingQuery(page,  sql,new JoinMapper());
		}	
	}
	
	@DataProvider
	public void getJoinJrfwyglPagebyDept(Page<JoinJrfwygl> page, Criteria criteria) throws Exception {		
		String deptId=((Dept)ContextHolder.getLoginUser().getDepts().get(0)).getCDept().getId();
		String sql = "SELECT\n"
				+ "			J.* \n"
				+ "		FROM\n"
				+ "			t_join_jrfwygl J\n"
				+ "		LEFT JOIN t_handle_dept D ON J.ID_ = D.JOIN_ID_\n"
				+"WHERE\n" 
				+"	J.INVALID_=0 and D.INVALID_=0 and D.DEPT_ID_ = :deptId ";
		if(!this.commonJdbcDao.containsProperty("state", criteria)){
			sql += "  and j.state_=30 ";
		}
		ParseResult result = this.commonJdbcDao.parseCriteria(criteria, true, "J");
		if (result != null) {
			StringBuffer sb = result.getAssemblySql();
			Map<String, Object> valueMap = result.getValueMap();
			valueMap.put("deptId", deptId);
			sql += " and "+sb.toString() +" order by J.CREATE_DATE_,J.UPDATE_DATE_ ";
			this.commonJdbcDao.pagingQuery(page, sql,new JoinMapper(),valueMap);
		} else {
			Map<String,Object> parameter = new HashMap<String,Object>();
			parameter.put("deptId", deptId);
			sql +=" order by J.CREATE_DATE_,J.UPDATE_DATE_ ";
			this.commonJdbcDao.pagingQuery(page,  sql,new JoinMapper(),parameter);
		}	
	}
	
	@Transactional
	@DataResolver
	private void saveEntity(BaseEntity entity) throws Exception{
		EntityState state=EntityUtils.getState(entity);
		if(state.equals(EntityState.NEW)){
			this.joinDao.save(entity);
		}
		else if(state.equals(EntityState.MODIFIED)){
			this.joinDao.update(entity);
		}
		else if(state.equals(EntityState.DELETED)){
			this.joinDao.delete(entity);
		}
	}
	
	@DataProvider
	public String getHandleDeptOpinionstr(Map<String, Object> params)throws Exception{
		String joinId = (String) params.get("joinId");
		String trainCz = (String) params.get("trainCz");
		if(StringUtils.isEmpty(trainCz))
			return "";
		List<String> users=new ArrayList<String>();
		users.add(trainCz);		
		List<Opinion> opinions=UfloUtils.getOpinions(null, joinId, "业务部门确认", null, users);
		if(opinions!=null&&opinions.size()>0)
			return opinions.get(0).getOpinion();
		else return "";
	}
	
	@Expose
	public String checkdept(List<Record> depts) throws Exception{
		for (Record dept : depts) {
			if (dept.getString("id").startsWith(Dept.NANNING) == false||StringUtils.isNotBlank(dept.getString("deptLevel"))) {
				return dept.getString("name") + ",不属于南宁中支的部门,请重新选择!";
			} else {
				List<IUser> users = SecurityUtils.getUserByRoleForDept(dept.getString("id"), Constants.ROLE_CZ);
				if (users.size() <= 0)
					return dept.getString("name") + "，未设置处长，请重新选择!";
			}
		}
		return null;
	}
	
	@DataResolver
	@Transactional
	public void updateJoinJrfwygl(JoinJrfwygl joinEntity) throws Exception{
		JoinJrfwygl join=EntityUtils.toEntity(joinEntity);
		this.saveEntity(join);
		List<HandleDept> depts=EntityUtils.getValue(join, "acceptDepts");
		if(depts!=null)
		{
			for (HandleDept dept : depts) {
				dept.setJoinId(joinEntity.getId());
				this.saveEntity(dept);
			}
		}
	}
	
	@DataResolver
	@Transactional
	public void updateHandleInfo (HandleInfo handleInfo) throws Exception{
		//System.out.println(handleInfo);
		this.saveEntity(handleInfo);
	}
	
	@DataProvider
	public Collection<Opinion>  getOpinions(String joinId)throws Exception{
		return UfloUtils.getOpinions(null, joinId, null,null, null);
	}
	
	@Expose
	public String getLoginUserDeptName()throws Exception{
		return ContextHolder.getLoginUser().getDepts().get(0).getName();
	}
	
	@DataProvider
	public Collection<IUser> getCzs() throws Exception {
		return SecurityUtils.getUserByRoleForDept(
				((Dept) ContextHolder.getLoginUser().getDepts().get(0)).getCDept().getId(), Constants.ROLE_CZ);
	}
		
		@FileResolver
		@DataResolver
		public Map<String, String> process1(UploadFile file,
				Map<String, Object> parameter) throws Exception {
			//String param1 = (String) parameter.get("param1");// 获取UploadAction的parameter对应的参数值
			//String param2 = (String) parameter.get("param2");// 获取UploadAction的parameter对应的参数值
			//Integer id= (Integer)parameter.get("id");
			
			//String fileId = (String)parameter.get("fileId");
			String filename=file.getFileName();
			String filesavename=UUID.randomUUID().toString();
			Path path=Paths.get(Configure.getString("JOIN_JRFWYGL_FILE_UPLOAD_PATH"), "");
			Files.createDirectories(path);
			path=path.resolve(filesavename);
			File destFile = Files.createFile(path).toFile();
			file.transferTo(destFile);
			Map<String, String> data = new HashMap<String, String>();
			data.put("fileName", filename);
			data.put("path", destFile.getAbsolutePath());
			//data.put("fileId", fileId);
			return data;
		}
		
		@FileProvider
		public DownloadFile download(Map<String, Object> parameter)throws Exception{
			String fileName =EscapeUtils.unescape((String)parameter.get("fileName"));
			//System.out.println(fileName);
			String path = EscapeUtils.unescape((String)parameter.get("path"));
			DownloadFile df=new DownloadFile(new File(path));//返回一个文件对象就可以
			df.setFileName( fileName);
			df.setName( fileName);
			return df;
		}

		@Transactional
		@DataResolver
		@Expose
		public void deleteJoinJrfwygl(JoinJrfwygl joinEntity) throws Exception{
			if(StringUtils.isNotEmpty(joinEntity.getPath()))
			Files.delete(Paths.get(joinEntity.getPath()));
			this.joinDao.delete(joinEntity);
		}
		
		@Transactional
		@DataResolver
		private void completeTask(String joinId,String taskId,String opinion,Map<String, Object> variables){
			long ltaskId = Long.parseLong(taskId);
			Task task = this.tc.getTask(ltaskId);
			if(variables!=null)
			this.pc.saveProcessVariables(task.getProcessInstanceId(), variables);
			final Opinion o = new Opinion();
			o.setBusKey(joinId);
			o.setBusTable(GetTableUtils.getTablename(JoinJrfwygl.class));
			o.setOpinion(opinion);
			o.setProcessInstanceId(task.getProcessInstanceId());
			o.setProcessName("加入金融服务与管理系统");
			o.setTaskId(ltaskId);
			o.setNodeName(task.getNodeName());
			o.setTaskName(task.getTaskName());
			o.setUsername(ContextHolder.getLoginUserName());
			o.setCname(ContextHolder.getLoginUser().getCname());
			o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
			o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
			this.coreHibernateDao.save(o);		
			this.tc.start(ltaskId);
			this.tc.complete(ltaskId);
		}
		
		@Expose
		@Transactional
		public void startProcess(Map<String, Object> params) throws Exception {
			String joinId = (String) params.get("joinId");
			String taskId = (String) params.get("taskId");
			if (StringUtils.isNotEmpty(taskId)) {
				this.completeTask(joinId, taskId, "修改后重新提交申请", params);			
			} else {	
				StartProcessInfo spi = new StartProcessInfo();
				spi.setBusinessId(joinId);
				spi.setPromoter(ContextHolder.getLoginUserName());
				spi.setCompleteStartTask(true);
				
				JoinJrfwygl entity = this.loadJoinJrfwygl(joinId);
				params.put("title", entity.getTitle());
				spi.setVariables(params);
				ProcessInstance pi=this.pc.startProcessByName("加入金融服务与管理系统", spi);
				final Opinion o = new Opinion();
				o.setBusKey(joinId);
				o.setBusTable(GetTableUtils.getTablename(JoinJrfwygl.class));
				o.setOpinion("提交申请");
				o.setProcessInstanceId(pi.getId());
				o.setProcessName("加入金融服务与管理系统");
				o.setTaskName("申请任务");
				o.setUsername(ContextHolder.getLoginUserName());
				o.setCname(ContextHolder.getLoginUser().getCname());
				o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
				o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
				this.coreHibernateDao.save(o);
			}
			
			JoinJrfwygl joinJrfwygl = this.joinDao.get(joinId, JoinJrfwygl.class);
			joinJrfwygl.setState(10);
			this.joinDao.update(joinJrfwygl);
		}
		
		@Expose
		public void cancelApply(Map<String, Object> params) throws Exception {
			String joinId = (String) params.get("joinId");
			String taskId = (String) params.get("taskId");
			String opinion = (String) params.get("opinion");
			long ltaskId = Long.parseLong(taskId);
			Task task = this.tc.getTask(ltaskId);
			final Opinion o = new Opinion();
			o.setBusKey(joinId);
			o.setBusTable(GetTableUtils.getTablename(JoinJrfwygl.class));
			o.setOpinion(opinion);
			o.setProcessInstanceId(task.getProcessInstanceId());
			o.setProcessName("加入金融服务与管理系统");
			o.setTaskId(ltaskId);
			o.setTaskName(task.getTaskName());
			o.setUsername(ContextHolder.getLoginUserName());
			o.setCname(ContextHolder.getLoginUser().getCname());
			o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
			o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
			this.coreHibernateDao.save(o);	
			this.tc.forward(ltaskId, "结束");
			
			JoinJrfwygl joinJrfwygl = this.joinDao.get(joinId, JoinJrfwygl.class);
			joinJrfwygl.setState(20);
			this.joinDao.update(joinJrfwygl);
		}
		

		@Expose
		@Transactional
		public void CZSH(Map<String, Object> params) throws Exception {
			String joinId = (String) params.get("joinId");
			String taskId = (String) params.get("taskId");
			String opinion = (String) params.get("opinion");
			boolean isagree = (boolean) params.get("isagree");
			Map<String, Object> variables=new HashMap<String, Object>();
			variables.put("agree", isagree ? 1:0);
			this.completeTask(joinId, taskId, opinion, variables);
		}
		

		@Expose
		@Transactional
		public void YWBMQR(Map<String, Object> params) throws Exception {
			final String handleDeptId = (String) params.get("handleDeptId");
			String taskId = (String) params.get("taskId");
			Integer opinion = (Integer) params.get("opinion");
			String opinionstr = (String) params.get("opinionstr");
			HandleDept handleDept=this.joinDao.get(handleDeptId, HandleDept.class);
			handleDept.setOpinion(opinion);
			handleDept.setTrainCz(ContextHolder.getLoginUserName());
			handleDept.setTrainCzCname(ContextHolder.getLoginUser().getCname());
			this.joinDao.update(handleDept);
			this.joinDao.doInHibernateSession(new ISessionCallback<Integer>() {
				@Override
				public Integer doInSession(Session session) {
					// TODO Auto-generated method stub
					Query query=session.createQuery("delete from "+HandleInfo.class.getName()+" where handleDeptId=:handleDeptId");
					query.setString("handleDeptId", handleDeptId);
					return query.executeUpdate();
				}
			});
			if(opinion==1){
				HandleInfo handleInfo=new HandleInfo();
				handleInfo.setHandleDeptId(handleDeptId);
				handleInfo.setOperationUsername((String) params.get("username"));
				handleInfo.setOperationCname((String) params.get("cname"));
				this.joinDao.save(handleInfo);
			}
			this.completeTask(handleDept.getJoinId(), taskId, opinionstr, null);
		}
		
		@Expose
		@Transactional
		public void CYQR(Map<String, Object> params) throws Exception {
			String joinId = (String) params.get("joinId");
			String taskId = (String) params.get("taskId");
			String opinion = (String) params.get("opinion");
			Integer isagree = (Integer) params.get("isagree");
			Map<String, Object> variables=new HashMap<String, Object>();
			variables.put("agree", isagree);
			this.completeTask(joinId, taskId, opinion, variables);
		}
		
		@Expose
		@Transactional
		public void CLFK(Map<String, Object> params) throws Exception {
			String taskId = (String) params.get("taskId");
			String joinId = (String) params.get("joinId");
			this.completeTask(joinId, taskId, "操作员反馈处理情况", null);
		}
		
		@Expose
		@Transactional
		public void FKQR(Map<String, Object> params) throws Exception {
			String joinId = (String) params.get("joinId");
			String taskId = (String) params.get("taskId");
			String opinion = (String) params.get("opinion");
			boolean isagree = (boolean) params.get("isagree");
			Map<String, Object> variables=new HashMap<String, Object>();
			variables.put("agree", isagree ? 1:0);
			this.completeTask(joinId, taskId, opinion, variables);
		}
		
}
